package com.freeSoft;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Properties;

public class CreateDaoImpl {
	private String tableName;
	private Properties prop;
	private ResultSetMetaData rs;
	public ResultSetMetaData getRs() {
		return rs;
	}

	public void setRs(ResultSetMetaData rs) {
		this.rs = rs;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public Properties getProp() {
		return prop;
	}
	
	public void setProp(Properties prop) {
		this.prop = prop;
	}
	
	public void generateDaoImpl(){
		String daoImplPath = prop.getProperty(Util.PROP_DAO_IMPL_PATH);
		String beanPath = prop.getProperty(Util.PROP_BEAN_PATH);
		String daoPath = prop.getProperty(Util.PROP_DAO_PATH);
		String outputDir = Util.getOutputDir(prop);
		String projactName = prop.getProperty(Util.PROJECT_NAME);
		String absolutePath = outputDir+ projactName + File.separator+ projactName+ Util.CORE_NAME +File.separator+ 
		"src"+File.separator+"main"+File.separator+"java"+File.separator+Util.javaPackToFilePath(daoImplPath);
		File f = new File(absolutePath);
		if ( !f.exists()){
			f.mkdirs();
		}
 
		String beanName = tableName.substring(0, 1).toUpperCase()+tableName.substring(1, tableName.length());
		beanName = Util.changeName(beanName);
 
		File file = new File(absolutePath+File.separator+beanName+"DaoImpl.java");
		try {
			PrintWriter out	   = new PrintWriter(new BufferedWriter( new FileWriter(file)));
			out.println("package "+daoImplPath +";\r\n");
			out.println();
			out.println("import java.util.List;");
			out.println("import java.util.ArrayList;");
			out.println("import java.sql.PreparedStatement;");
			out.println("import java.sql.ResultSet;");
			out.println("import java.sql.SQLException;");
			out.println("import java.sql.PreparedStatement;");
			out.println("import org.springframework.jdbc.core.JdbcTemplate;");
			out.println("import org.springframework.jdbc.core.PreparedStatementSetter;");
			out.println("import org.springframework.jdbc.core.RowCallbackHandler;");
			out.println();
			beanName = Util.changeName(beanName);
			out.println("import "+beanPath+"."+beanName+";");
			out.println("import "+ daoPath+"."+beanName+"Dao;");
			
			StringBuffer headerArea = new StringBuffer();
			StringBuffer bufUpdateMethod = new StringBuffer();
			createUpdateMethod( beanName,bufUpdateMethod, headerArea);
			
			StringBuffer bufInsertMethod = new StringBuffer();
			createInsertMethod( beanName,bufInsertMethod, headerArea);
			
			StringBuffer bufGetBeanByIdMethod = new StringBuffer();
			createGetBeanById(beanName,bufGetBeanByIdMethod);
			
			StringBuffer bufGetAllBeandMethod = new StringBuffer();
			createGetAllBean(beanName,bufGetAllBeandMethod);
			
			out.print(headerArea.toString());
			
			out.println("public class "+ beanName +"DaoImpl implements "+ beanName+"Dao"+"  { ");
			out.println("	private JdbcTemplate jdbcTemplate;");
			out.println("	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { ");
			out.println("		this.jdbcTemplate = jdbcTemplate;");
			out.println("	}");
			out.println("");
			createDelMethod(beanName,out);
			out.println( bufUpdateMethod.toString());
			out.println( bufInsertMethod.toString());
			out.println( bufGetBeanByIdMethod.toString());
			out.println( bufGetAllBeandMethod.toString());
			out.println("}");
			out.flush();
			out.close();
		}catch(Exception e){
			
		}
	}
	private void createGetBeanById(String beanName,StringBuffer getBeanByIdBuf){
		 StringBuffer processRowBuf = new StringBuffer();
		 String space = " 							";
		 processRowBuf.append(space+beanName+" to= new "+beanName+"();\r\n");
		 try {
			for(int i=1;i<=rs.getColumnCount();i++){
				if ( !rs.getSchemaName(i).toLowerCase().equals("id")){
					String columnName = rs.getColumnName(i);
					String methodName = columnName.substring(0, 1).toUpperCase()+columnName.substring(1, columnName.length());
					String typeName =  rs.getColumnTypeName(i);
					String fieldType =Util.changeJDBCTypeToJavaType(typeName);
				 
					if ( fieldType.equals(""))
						fieldType = Util.getDataType(rs.getColumnType(i), rs.getScale(i));
					fieldType = fieldType.substring(0, 1).toUpperCase()+fieldType.substring(1, fieldType.length());
					processRowBuf.append(space+"to.set"+methodName+"(rs.get"+fieldType+"(\""+columnName+"\"));\r\n");
				}
			}
			processRowBuf.append(space+"result.add(to);\r\n");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		String  insertStr = "	String SQL_GET_"+beanName.toUpperCase()+"_BYID=\" SELECT * FROM  "+tableName+"  WHERE id=?\";";
		getBeanByIdBuf.append(insertStr+"\r\n");
		getBeanByIdBuf.append("	public   List<"+beanName+">  get"+beanName+"ById(final int keyValue) {\r\n");
		getBeanByIdBuf.append("		final List<"+beanName+"> result = new ArrayList<"+beanName+">();\r\n");
		getBeanByIdBuf.append("		try {\r\n");
		getBeanByIdBuf.append("			jdbcTemplate.query(\r\n");
		getBeanByIdBuf.append("				SQL_GET_"+beanName.toUpperCase()+"_BYID,\r\n");
		getBeanByIdBuf.append("				new PreparedStatementSetter() {\r\n");
		getBeanByIdBuf.append("					public void setValues(PreparedStatement ps)	throws SQLException {\r\n");
		getBeanByIdBuf.append("						ps.setInt(1, keyValue);\r\n");
		getBeanByIdBuf.append("					}\r\n");
		getBeanByIdBuf.append("				},\r\n");
		getBeanByIdBuf.append("				new RowCallbackHandler() { \r\n");
		getBeanByIdBuf.append("						public void processRow(ResultSet rs) throws SQLException {\r\n");
		getBeanByIdBuf.append( processRowBuf.toString());
		getBeanByIdBuf.append("						}\r\n");
		getBeanByIdBuf.append("				}\r\n");
		getBeanByIdBuf.append("			);\r\n");
		getBeanByIdBuf.append("		} catch (Exception e) {\r\n");
		getBeanByIdBuf.append("			e.printStackTrace();\r\n");
		getBeanByIdBuf.append("		}\r\n");
		getBeanByIdBuf.append("		return result;\r\n");
		
		getBeanByIdBuf.append("	}\r\n");
	}
	private void createGetAllBean(String beanName,StringBuffer getAllBeanBuf){
		StringBuffer processRowBuf = new StringBuffer();
		String space = " 							";
		processRowBuf.append(space+beanName+" to= new "+beanName+"();\r\n");
		try {
			for(int i=1;i<=rs.getColumnCount();i++){
				if ( !rs.getSchemaName(i).toLowerCase().equals("id")){
					String columnName = rs.getColumnName(i);
					String methodName = columnName.substring(0, 1).toUpperCase()+columnName.substring(1, columnName.length());
					String typeName =  rs.getColumnTypeName(i);
					String fieldType =Util.changeJDBCTypeToJavaType(typeName);
					
					if ( fieldType.equals(""))
						fieldType = Util.getDataType(rs.getColumnType(i), rs.getScale(i));
					fieldType = fieldType.substring(0, 1).toUpperCase()+fieldType.substring(1, fieldType.length());
					processRowBuf.append(space+"to.set"+methodName+"(rs.get"+fieldType+"(\""+columnName+"\"));\r\n");
				}
			}
			processRowBuf.append(space+"result.add(to);\r\n");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		String  insertStr = "	String SQL_GET_ALL_"+beanName.toUpperCase()+"=\" SELECT * FROM  "+tableName+" WHERE id=?\";";
		getAllBeanBuf.append(insertStr+"\r\n");
		getAllBeanBuf.append("	public List<"+beanName+"> getAll"+beanName+"( ) {\r\n");
		getAllBeanBuf.append("		final List<"+beanName+"> result = new ArrayList<"+beanName+">();\r\n");
		getAllBeanBuf.append("		try {\r\n");
		getAllBeanBuf.append("			 jdbcTemplate.query(\r\n");
		getAllBeanBuf.append("				SQL_GET_ALL_"+beanName.toUpperCase()+",\r\n");
		getAllBeanBuf.append("				new RowCallbackHandler() {\r\n ");
		getAllBeanBuf.append("					public void processRow(ResultSet rs) throws SQLException {\r\n");
		getAllBeanBuf.append( processRowBuf.toString());
		getAllBeanBuf.append("					}\r\n");
		getAllBeanBuf.append("				}\r\n");
		getAllBeanBuf.append("			);\r\n");
		getAllBeanBuf.append("		} catch (Exception e) {\r\n");
		getAllBeanBuf.append("			e.printStackTrace();\r\n");
		getAllBeanBuf.append("		}\r\n");
		getAllBeanBuf.append("		return result;\r\n");
		getAllBeanBuf.append("	}\r\n");
	}
	
	private void createInsertMethod(String beanName,StringBuffer updateBuf,StringBuffer headerArea){
		StringBuffer bufSql = new StringBuffer();
		StringBuffer bufSetting = new StringBuffer();
		String space = "						";
		bufSql.append("  VALUES( ");
		try {
			for(int i=1;i<=rs.getColumnCount();i++){
				if ( !rs.getSchemaName(i).toLowerCase().equals("id")){
					if (i==1){
						bufSql.append(  rs.getColumnName(i));
						fillSettingValue(i,bufSetting,null,Util.changeInitialToLower(beanName));
					}
					else {
						bufSql.append( ","+rs.getColumnName(i));
						fillSettingValue(i,bufSetting,null,Util.changeInitialToLower(beanName));
					}
				}
			}
			bufSql.append("  WHERE id=?\";\r\n");
//			bufSetting.append(space+"ps.setInt("+rs.getColumnCount()+","+beanName+".getInt());\r\n");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		String  insertStr = "	String SQL_INSERT_"+beanName.toUpperCase()+"=\" INSERT INTO "+tableName+bufSql.toString();
		updateBuf.append(insertStr+"\r\n");
		updateBuf.append("	public int insert"+beanName+"(final "+beanName+" " + Util.changeInitialToLower(beanName) +") {\r\n");
		updateBuf.append("		int rtv = 0;\r\n");
		updateBuf.append("		try {\r\n");
		updateBuf.append("			rtv = jdbcTemplate.update(\r\n");
		updateBuf.append("				SQL_INSERT_"+beanName.toUpperCase()+",\r\n");
		updateBuf.append("				new PreparedStatementSetter() {\r\n");
		updateBuf.append("					public void setValues(PreparedStatement ps)	throws SQLException {\r\n");
		updateBuf.append(bufSetting.toString() );
		updateBuf.append("					}\r\n");
		updateBuf.append("				}\r\n");
		updateBuf.append("			);\r\n");
		updateBuf.append("		} catch (Exception e) {\r\n");
		updateBuf.append("			e.printStackTrace();\r\n");
		updateBuf.append("		}\r\n");
		updateBuf.append("		return rtv;\r\n");
		updateBuf.append("	}\r\n");
	}
	private void fillSettingValue(int column,StringBuffer bufSetting,StringBuffer headerArea,String beanName){
		String fieldName;
		String space = "						";
		try {
			fieldName = rs.getColumnName(column);
			fieldName = fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1, fieldName.length());
			String typeName = rs.getColumnTypeName(column);
			String fieldType =Util.changeJDBCTypeToJavaType(typeName);
			String importPath = Util.getImportPath(typeName);
			if ( headerArea!=null && ! importPath.equals("")){
				headerArea.append("import "+importPath+"\r\n");
			}
			if ( fieldType.equals(""))
				fieldType = Util.getDataType(rs.getColumnType(column), rs.getScale(column));
			fieldType = fieldType.substring(0, 1).toUpperCase()+fieldType.substring(1, fieldType.length());
			bufSetting.append(space+"ps.set"+fieldType+"("+column+","+beanName+".get"+fieldName+"());\r\n");			
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
	private void createUpdateMethod(String beanName,StringBuffer updateBuf,StringBuffer headerArea){
		StringBuffer bufSql = new StringBuffer();
		StringBuffer bufSetting = new StringBuffer();
		String space = "						";
		bufSql.append(" SET ");
		try {
			for(int i=1;i<=rs.getColumnCount();i++){
				if ( !rs.getSchemaName(i).toLowerCase().equals("id")){
					if (i==1){
						bufSql.append(  rs.getColumnName(i)+"=? ");
						fillSettingValue(i,bufSetting,headerArea,Util.changeInitialToLower(beanName));
					}
					else {
						bufSql.append( ","+rs.getColumnName(i)+"=? ");
						fillSettingValue(i,bufSetting,headerArea,Util.changeInitialToLower(beanName));
					}
				}
			}
			bufSql.append("  WHERE id=?\";\r\n");
//			bufSetting.append(space+"ps.setInt("+rs.getColumnCount()+","+beanName+".getInt());\r\n");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		String  updateStr = "\r\n	String SQL_UPDATE_"+beanName.toUpperCase()+"=\" UPDATE "+tableName+bufSql.toString();
		updateBuf.append(updateStr+"\r\n");
		updateBuf.append("	public int update"+beanName+"(final "+ beanName +"  "+Util.changeInitialToLower(beanName)+") {\r\n");
		updateBuf.append("		int rtv = 0;\r\n");
		updateBuf.append("		try {\r\n");
		updateBuf.append("			rtv = jdbcTemplate.update(\r\n");
		updateBuf.append("				SQL_UPDATE_"+beanName.toUpperCase()+",\r\n");
		updateBuf.append("				new PreparedStatementSetter() {\r\n");
		updateBuf.append("					public void setValues(PreparedStatement ps)	throws SQLException {\r\n");
		updateBuf.append(bufSetting.toString() );
		updateBuf.append("					}\r\n");
		updateBuf.append("				}\r\n");
		updateBuf.append("			);\r\n");
		updateBuf.append("		} catch (Exception e) {\r\n");
		updateBuf.append("			e.printStackTrace();\r\n");
		updateBuf.append("		}\r\n");
		updateBuf.append("		return rtv;\r\n");
		updateBuf.append("	}\r\n");
	}
	
	private void createDelMethod(String beanName,PrintWriter out){
		String  deleteStr = "	String SQL_DELETE_"+beanName.toUpperCase()+"=\" DELETE FROM  tableName WHERE id=?\";";
		out.println(deleteStr);
		out.println("	public int  delete"+beanName+"(final int keyValue) {");
		out.println("		int rtv = 0;");
		out.println("		try {");
		out.println("			rtv = jdbcTemplate.update(");
		out.println("				 SQL_DELETE_"+beanName.toUpperCase()+",");
		out.println("				new PreparedStatementSetter() {");
		out.println("					public void setValues(PreparedStatement ps)	throws SQLException {");
		out.println("						ps.setInt(1, keyValue);");
		out.println("					}");
		out.println("				}");
		out.println("			);");
		out.println("		} catch (Exception e) {");
		out.println("			e.printStackTrace();");
		out.println("		}");
		out.println("		return rtv;");
		out.println("	}");
	}
	
}
